﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.TextEditor;
using WeifenLuo.WinFormsUI.Docking;
using System.IO;
using tiDE.API.Utility;
using tiDE.API;
using tiDE;
using System.Runtime.Serialization.Formatters.Binary;
using tiDE.Runtime;
using DCS7Design;
using System.Threading;
using tiDE.Packers;
using System.Reflection;
using System.Diagnostics;
using tiDE.Settings;
using System.Text.RegularExpressions;
using tiDE.CodeFolding;
using tiDE.CodeCompletion;
using tiDE.SourceInsight;
using tiDE.KeyboardManager;
using Basic;
using tiDE.AddIns;

namespace tiDE
{
    public partial class tiDEWindow : Form
    {
        OutputWindow outputWindow;
        ErrorWindow errors;
        List<CodeWindow> OpenWindows;
        SolutionExplorer Explorer;
        Solution _CurrentSolution = null;
        public Solution CurrentSolution
        {
            get
            {
                return _CurrentSolution;
            }
            set
            {
                _CurrentSolution = value;
                if (_CurrentSolution == null)
                {
                    ProjectClosedLayout();
                    this.Text = "tiDE";
                }
                else
                {
                    this.Text = CurrentSolution.Name + " - tiDE";
                }
            }
        }
        public static string CurrentSolutionFile, CurrentSolutionDirectory; // TODO: Better permissions
        public Dictionary<string, Type> InstalledPackers;

        public static Guid Guid = new Guid("d8707db7-c2ed-4dc2-86eb-1fc7b63783d9");
        public static Version Version = new Version(0, 0, 0, 1);
        public static string TextualVersion = "0.0.0.1 Pre-Release";
        public static GlobalSettings GlobalSettings;
        public static tiDEWindow ThisInstance;
        public static AddInProvider AddInProvider;

        //TODO make this have actual values
        //The purpose of the NullProject would be for any file without a solution
        public static Project NullProject = new Project("", "", null, "", null, null, "", "");

        #region Constants
        const string GenericFilter = "Code Files (*.z80, *.asm, *.inc, *.c, *.tib)|*.z80;*.asm;*.inc;*.c;*.tib|Image Files (*.bmp, *.png, *.jpg, *.8xi)|*.bmp;*.png;*.jpg;*.8xi|Binaries (*.8xp, *.8xk, *.8xu)|*.8xp;*.8xk;*.8xu|All Files|*.*";
        #endregion

        #region Default Auto-Replacements
        List<AutoReplacement> TIBasicReplacements = new List<AutoReplacement>(new AutoReplacement[]
            {
                new AutoReplacement(">DMS", "►DMS"),
                new AutoReplacement(">Dec", "►Dec"),
                new AutoReplacement(">Frac", "►Frac"),
                new AutoReplacement("->", "→"),
                new AutoReplacement("^^r", "ʳ"),
                new AutoReplacement("^^o", "°"),
                new AutoReplacement("^^-1", "⁻¹"),
                new AutoReplacement("^^2", "²"),
                new AutoReplacement("^^T", "ᵀ"),
                new AutoReplacement("^^3", "³"),
                new AutoReplacement("R>Pr(", "R►Pr("),
                new AutoReplacement("R>Ptheta(", "R►Ptheta("),
                new AutoReplacement("P>Rx(", "P►Rx("),
                new AutoReplacement("P>Ry(", "P►Ry("),
                new AutoReplacement("|E", "ᴇ"),
                new AutoReplacement("|theta", "θ"),
                new AutoReplacement("|i", "ί"),
                new AutoReplacement("L1", "L₁"),
                new AutoReplacement("L2", "L₂"),
                new AutoReplacement("L3", "L₃"),
                new AutoReplacement("L4", "L₄"),
                new AutoReplacement("L5", "L₅"),
                new AutoReplacement("L6", "L₆"),
                new AutoReplacement("Y1", "Y₁"),
                new AutoReplacement("Y2", "Y₂"),
                new AutoReplacement("Y3", "Y₃"),
                new AutoReplacement("Y4", "Y₄"),
                new AutoReplacement("Y5", "Y₅"),
                new AutoReplacement("Y6", "Y₆"),
                new AutoReplacement("Y7", "Y₇"),
                new AutoReplacement("Y8", "Y₈"),
                new AutoReplacement("Y9", "Y₉"),
                new AutoReplacement("Y0", "Y₀"),
                new AutoReplacement("X1T", "X₁ᴛ"),
                new AutoReplacement("Y1T", "Y₁ᴛ"),
                new AutoReplacement("X2T", "X₂ᴛ"),
                new AutoReplacement("Y2T", "Y₂ᴛ"),
                new AutoReplacement("X3T", "X₃ᴛ"),
                new AutoReplacement("Y3T", "Y₃ᴛ"),
                new AutoReplacement("X4T", "X₄ᴛ"),
                new AutoReplacement("Y4T", "Y₄ᴛ"),
                new AutoReplacement("X5T", "X₅ᴛ"),
                new AutoReplacement("Y5T", "Y₅ᴛ"),
                new AutoReplacement("X6T", "X₆ᴛ"),
                new AutoReplacement("Y6T", "Y₆ᴛ"),
                new AutoReplacement("r1", "r₁"),
                new AutoReplacement("r2", "r₂"),
                new AutoReplacement("r3", "r₃"),
                new AutoReplacement("r4", "r₄"),
                new AutoReplacement("r5", "r₅"),
                new AutoReplacement("r6", "r₆"),
                new AutoReplacement("|xhat", "ẋ"),
                new AutoReplacement("|Sigmax", "Σx"),
                new AutoReplacement("|Sigmax^2", "Σx^2"),
                new AutoReplacement("|sigmax", "σx"),
                new AutoReplacement("|yhat", "ȳ"),
                new AutoReplacement("|Sigmay", "Σy"),
                new AutoReplacement("|Sigmay^2", "Σy^2"),
                new AutoReplacement("|sigmay", "σy"),
                new AutoReplacement("|Sigmaxy", "Σxy"),
                new AutoReplacement("|x1", "x₁"),
                new AutoReplacement("|x2", "x₂"),
                new AutoReplacement("|x3", "x₃"),
                new AutoReplacement("|y1", "y₁"),
                new AutoReplacement("|y2", "y₂"),
                new AutoReplacement("|y3", "y₃"),
                new AutoReplacement("|chi^2", "χ^2"),
                new AutoReplacement("|phat", "ṗ"),
                new AutoReplacement("|phat1", "ṗ1"),
                new AutoReplacement("|phat2", "ṗ2"),
                new AutoReplacement("|xhat1", "ẋ1"),
                new AutoReplacement("|Sx1", "Sx₁"),
                new AutoReplacement("|n1", "n₁"),
                new AutoReplacement("|xhat2", "ẋ2"),
                new AutoReplacement("|Sx2", "Sx₂"),
                new AutoReplacement("|n2", "n₂"),
                new AutoReplacement("|r^2", "r²"),
                new AutoReplacement("|R^2", "R²"),
                new AutoReplacement("Un-1", "Un-₁"),
                new AutoReplacement("Vn-1", "Vn-₁"),
                new AutoReplacement("|thetaMin", "θMin"),
                new AutoReplacement("|thetaMax", "θMax"),
                new AutoReplacement("|Zthetamin", "Zθmin"),
                new AutoReplacement("|Zthetamax", "Zθmax"),
                new AutoReplacement("|DeltaTbl", "∆Tbl"),
                new AutoReplacement("|thetastep", "θstep"),
                new AutoReplacement("|Zthetastep", "Zθstep"),
                new AutoReplacement("|DeltaX", "∆X"),
                new AutoReplacement("|DeltaY", "∆Y"),
                new AutoReplacement("<=", "≤"),
                new AutoReplacement(">=", "≥"),
                new AutoReplacement("=/=", "≠"),
                new AutoReplacement("|plotsquare", "□"),
                new AutoReplacement("|plotcross", "﹢"),
                new AutoReplacement("|plotdot", "·"),
                new AutoReplacement("|pi", "π"),
                new AutoReplacement("|~", "⁻"),
                new AutoReplacement("SigmaPrn(", "ΣPrn("),
                new AutoReplacement("SigmaInt(", "ΣInt("),
                new AutoReplacement(">Nom(", "►Nom("),
                new AutoReplacement(">Eff(", "►Eff("),
                new AutoReplacement("chi^2cdf(", "χ^2cdf("),
                new AutoReplacement("chi^2pdf(", "χ^2pdf("),
                new AutoReplacement(">Rect", "►Rect"),
                new AutoReplacement(">Polar", "►Polar"),
                new AutoReplacement("Shadechi^2(", "Shadeχ^2("),
                new AutoReplacement("Matr>list(", "Matr►list("),
                new AutoReplacement("List>matr(", "List►matr("),
                new AutoReplacement("chi^2-Test(", "χ^2-Test("),
                new AutoReplacement("re^thetai", "re^θi"),
                new AutoReplacement("Equ>String(", "Equ►String("),
                new AutoReplacement("String>Equ(", "String►Equ("),
                new AutoReplacement("|'", "´"),
                new AutoReplacement("|:", "¨"),
                new AutoReplacement("|?", "¿"),
                new AutoReplacement("|!", "¡"),
                new AutoReplacement("|alpha", "α"),
                new AutoReplacement("|beta", "β"),
                new AutoReplacement("|gamma", "γ"),
                new AutoReplacement("|Delta", "Δ"),
                new AutoReplacement("|delta", "δ"),
                new AutoReplacement("|epsilon", "ε"),
                new AutoReplacement("|lambda", "λ"),
                new AutoReplacement("|mu", "μ"),
                new AutoReplacement("|greek_pi", "π"),
                new AutoReplacement("|rho", "ρ"),
                new AutoReplacement("|Sigma", "Σ"),
                new AutoReplacement("|Phi", "Φ"),
                new AutoReplacement("|Omega", "Ω"),
                new AutoReplacement("|phat", "ṗ"),
                new AutoReplacement("|chi", "χ"),
                new AutoReplacement("|sigma", "σ"),
                new AutoReplacement("|tau", "τ"),
                new AutoReplacement("|...", "…"),
                new AutoReplacement("|<", "∠"),
                new AutoReplacement("|sharps", "ß"),
                new AutoReplacement("|x", "ˣ"),
                new AutoReplacement("|smallT", "ᴛ"),
                new AutoReplacement("|small0", "₀"),
                new AutoReplacement("|small1", "₁"),
                new AutoReplacement("|small2", "₂"),
                new AutoReplacement("|small3", "₃"),
                new AutoReplacement("|small4", "₄"),
                new AutoReplacement("|small5", "₅"),
                new AutoReplacement("|small6", "₆"),
                new AutoReplacement("|small7", "₇"),
                new AutoReplacement("|small8", "₈"),
                new AutoReplacement("|small9", "₉"),
                new AutoReplacement("|small10", "₁₀"),
                new AutoReplacement("<|", "◄"),
                new AutoReplacement("|>", "►"),
                new AutoReplacement("|uparrow", "↑"),
                new AutoReplacement("|downarrow", "↓"),
                new AutoReplacement("|xmark", "×"),
                new AutoReplacement("|integral", "∫"),
                new AutoReplacement("|squareroot", "√"),
                new AutoReplacement("sqrt(", "√("),
                new AutoReplacement("cuberoot(", "³√("),
                new AutoReplacement("10^(", "₁₀^("),
                new AutoReplacement("sin-1(", "sin⁻¹("),
                new AutoReplacement("cos-1(", "cos⁻¹("),
                new AutoReplacement("tan-1(", "tan⁻¹("),
                new AutoReplacement("sinh-1(", "sinh⁻¹("),
                new AutoReplacement("cosh-1(", "soch⁻¹("),
                new AutoReplacement("tanh-1(", "tanh⁻¹("),
                new AutoReplacement("|L", "˪"),
                new AutoReplacement("chi^2GOF-Test(", "χ^2GOF-Test("),
                new AutoReplacement(">n/d<>Un/d", "►n/d◄►Un/d"),
                new AutoReplacement(">F<>D", "►F◄►D"),
                new AutoReplacement("Sigma(", "Σ("),
                new AutoReplacement("|n/d", "n⁄d"),
                new AutoReplacement("|Un/d", "Un⁄d"),
                new AutoReplacement("|xroot", "ˣ√"),
            });
        #endregion

        public tiDEWindow()
        {
            ThisInstance = this;
            RuntimeData.tiDEDirectory = DataConverter.GetDirectoryFromFile(Assembly.GetExecutingAssembly().Location);
            SetUpUserFolder();
            InitializeComponent();
            LoadGlobalSettings();
            OpenWindows = new List<CodeWindow>();
            StartPage page = new StartPage();
            outputWindow = new OutputWindow();
            errors = new ErrorWindow();
            Explorer = new SolutionExplorer();
            Explorer.OpenFileRequested += new EventHandler<FileActionEventArgs>(Explorer_OpenFileRequested);
            Explorer.NewFileRequested += new EventHandler<NewFileEventArgs>(Explorer_NewFileRequested);
            Explorer.AddExistingRequested += new EventHandler<NewFileEventArgs>(Explorer_AddExistingRequested);
            Explorer.RenameFileRequested += new EventHandler<RenameFileEventArgs>(Explorer_RenameFileRequested);
            Explorer.DeleteFileRequested += new EventHandler<FileActionEventArgs>(Explorer_DeleteFileRequested);
            Explorer.NavigateToLocationRequested += new EventHandler<NavigateToLocationEventArgs>(Explorer_NavigateToLocationRequested);
            page.NewProject += new EventHandler(newProject);
            page.OpenProject += new EventHandler(page_OpenProject);
            page.RecentProjectSelected += new EventHandler<OpenProjectArgs>(page_RecentProjectSelected);
            page.Show(dockPanel1, DockState.Document);
            dockPanel1.ActiveContentChanged += new EventHandler(dockPanel1_ActiveContentChanged);
            InstalledPackers = new Dictionary<string, Type>();
            // Source Insight
            InsightManager.AddInsightProvier(new z80SourceInsight());
            InsightManager.AddInsightProvier(new AxeSourceInsight());
            InsightManager.AddInsightProvier(new TIBasicSourceInsight());
            // Default packers
            InstalledPackers.Add("83PlusProgram", typeof(Program83PlusPacker));
            InstalledPackers.Add("83PlusOS", typeof(OS83PlusPacker));
            InstalledPackers.Add("83PlusApplication", typeof(Application83PlusPacker));
            // Default folding strategies
            CodeWindow.FoldingStrategies = new Dictionary<string, Type>();
            CodeWindow.FoldingStrategies.Add("z80", typeof(z80Folding));
            CodeWindow.FoldingStrategies.Add("asm", typeof(z80Folding));
            CodeWindow.FoldingStrategies.Add("inc", typeof(z80Folding));
            CodeWindow.FoldingStrategies.Add("tib", typeof(TIBasicFolding));
            CodeWindow.FoldingStrategies.Add("axe", typeof(AxeFolding));
            List<AutoReplacement> AxeReplacements = TIBasicReplacements;
            AxeReplacements.AddRange(new AutoReplacement[]
            {
                new AutoReplacement("DispGraphr", "DispGraphʳ"),
                new AutoReplacement("DispGraphʳr", "DispGraphʳʳ"),
                new AutoReplacement("ClrDrawr", "ClrDrawʳ"),
                new AutoReplacement("DispGraphʳr", "DispGraphʳʳ"),
                new AutoReplacement("DrawInvr", "DrawInv ʳ"),
                new AutoReplacement("DrawInv r", "DrawInv ʳ"),
                new AutoReplacement("DrawInvr", "DrawInv ʳ"),
                new AutoReplacement("Horizontal +r", "Horizontal +ʳ"),
                new AutoReplacement("Horizontal -r", "Horizontal -ʳ"),
                new AutoReplacement("Vertical +r", "Vertical +ʳ"),
                new AutoReplacement("Vertical -r", "Vertical -ʳ"),
                new AutoReplacement("}r", "}ʳ"),
                new AutoReplacement("}ʳ", "}ʳʳ"),
                new AutoReplacement(")r", ")ʳ"),

            });
            CodeWindow.AutomaticReplacements.Add("tib", TIBasicReplacements);
            CodeWindow.AutomaticReplacements.Add("axe", AxeReplacements);
            CodeWindow.CodeCompleters.Add("z80", new z80CodeCompletion());
            CodeWindow.CodeCompleters.Add("asm", new z80CodeCompletion());
            CodeWindow.CodeCompleters.Add("inc", new z80CodeCompletion());
            CodeWindow.CodeCompleters.Add("tib", new TIBasicCodeCompletion());

            AddInProvider = new AddInProvider();
            try
            {
                AddInProvider.LoadAddIn(@"C:\tideboot\tiDEBootAddIn\tiDEBootAddIn\bin\Debug\tiDEBootAddIn.dll");
            }
            catch { } // Only works on my machine
        }

        void Explorer_NavigateToLocationRequested(object sender, NavigateToLocationEventArgs e)
        {
            OpenCodeWindow(CurrentSolutionDirectory + e.File);
            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = new TextLocation(e.Index, e.Line);
            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();

        }

        void page_RecentProjectSelected(object sender, OpenProjectArgs e)
        {
            BinaryFormatter format = new BinaryFormatter();
            StreamReader reader = new StreamReader(e.ProjectFile);
            CurrentSolution = (Solution)format.Deserialize(reader.BaseStream);
            CloseAllWindows();
            reader.Close();
            CurrentSolutionFile = e.ProjectFile;
            CurrentSolutionDirectory = DataConverter.GetDirectoryFromFile(CurrentSolutionFile);
            List<string> newOpenFiles = new List<string>();
            foreach (string file in CurrentSolution.OpenFiles)
            {
                if (File.Exists(CurrentSolutionDirectory + file))
                {
                    OpenCodeWindow(CurrentSolutionDirectory + file);
                    newOpenFiles.Add(file);
                }
            }
            _CurrentSolution.OpenFiles = newOpenFiles;
            ProjectLayout();
            Explorer.UpdateSolution(_CurrentSolution);
            if (GlobalSettings.RecentSolutions.Contains(e.ProjectFile))
                GlobalSettings.RecentSolutions.Remove(e.ProjectFile);
            GlobalSettings.RecentSolutions.Add(e.ProjectFile);
            SaveGlobalSettings();
        }

        private void LoadGlobalSettings()
        {
            GlobalSettings = new GlobalSettings();
            try
            {
                if (!File.Exists(RuntimeData.tiDEUserDirectory + "\\Settings\\globalSettings.stg"))
                    return;
                BinaryFormatter format = new BinaryFormatter();
                Stream stream = File.Open(RuntimeData.tiDEUserDirectory + "\\Settings\\globalSettings.stg", FileMode.Open);
                GlobalSettings = (GlobalSettings)format.Deserialize(stream);
                stream.Close();
                if (GlobalSettings.CustomTools == null)
                    GlobalSettings.CustomTools = new List<CustomTool>();
                if (GlobalSettings.RecentSolutions == null)
                    GlobalSettings.RecentSolutions = new List<string>();
                if (GlobalSettings.ShortcutManager == null)
                    GlobalSettings.ShortcutManager = new ShortcutManager();
                SaveGlobalSettings();
                UpdateCustomTools();
            }
            catch { }
        }

        private void SaveGlobalSettings()
        {
            Stream stream = File.Create(RuntimeData.tiDEUserDirectory + "\\Settings\\globalSettings.stg");
            BinaryFormatter format = new BinaryFormatter();
            format.Serialize(stream, GlobalSettings);
            stream.Close();
        }

        void Explorer_DeleteFileRequested(object sender, FileActionEventArgs e)
        {
            if (File.Exists(CurrentSolutionDirectory + e.File))
                File.Delete(CurrentSolutionDirectory + e.File);
            foreach (Project project in _CurrentSolution.Projects)
            {
                if (CurrentSolutionDirectory + project.RootDirectory + "\\" ==
                    CurrentSolutionDirectory + DataConverter.GetDirectoryFromFile(e.File))
                {
                    project.Files.Remove(DataConverter.StripDirectory(e.File));
                    if (_CurrentSolution.OpenFiles.Contains(e.File))
                        _CurrentSolution.OpenFiles.Remove(e.File);
                    if (_CurrentSolution.FocusedFile == e.File)
                        _CurrentSolution.FocusedFile = "";
                    SaveSolutionAndProjects();
                    break;
                }
            }
            Explorer.UpdateSolution(_CurrentSolution);
        }

        void Explorer_RenameFileRequested(object sender, RenameFileEventArgs e)
        {
            try
            {
                File.Copy(CurrentSolutionDirectory + e.File,
                    CurrentSolutionDirectory + DataConverter.GetDirectoryFromFile(e.File) + e.NewName);
                File.Delete(CurrentSolutionDirectory + e.File);
                foreach (Project project in _CurrentSolution.Projects)
                {
                    if (CurrentSolutionDirectory + project.RootDirectory + "\\" ==
                        CurrentSolutionDirectory + DataConverter.GetDirectoryFromFile(e.File))
                    {
                        project.Files.Remove(DataConverter.StripDirectory(e.File));
                        project.Files.Add(e.NewName);
                        if (_CurrentSolution.OpenFiles.Contains(e.File))
                        {
                            _CurrentSolution.OpenFiles.Remove(e.File);
                            _CurrentSolution.OpenFiles.Add(project.RootDirectory + e.NewName);
                        }
                        SaveSolutionAndProjects();
                        break;
                    }
                }
                Explorer.UpdateSolution(_CurrentSolution);
            }
            catch { }
        }

        void Explorer_AddExistingRequested(object sender, NewFileEventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.FileName = "";
            dialog.Filter = "";
            dialog.Multiselect = true;
            if (dialog.ShowDialog() != DialogResult.OK)
                return;
            foreach (string FileName in dialog.FileNames)
            {
                e.Project.Files.Add(DataConverter.StripDirectory(FileName));
                if (!File.Exists(CurrentSolutionDirectory + "\\" + e.Project.RootDirectory + "\\" + DataConverter.StripDirectory(FileName)))
                    File.Copy(FileName, CurrentSolutionDirectory + "\\" + e.Project.RootDirectory + "\\" + DataConverter.StripDirectory(FileName));
            }
            if (dialog.FileNames.Length == 1)
            {
                OpenCodeWindow(CurrentSolutionDirectory + "\\" + e.Project.RootDirectory + "\\" + DataConverter.StripDirectory(dialog.FileName));
            }
            Explorer.UpdateSolution(_CurrentSolution);
            SaveSolutionAndProjects();
        }

        private void SaveSolutionAndProjects()
        {
            BinaryFormatter format = new BinaryFormatter();
            if (File.Exists(CurrentSolutionFile))
                File.Delete(CurrentSolutionFile);
            Stream solutionStream = File.Create(CurrentSolutionFile);
            format.Serialize(solutionStream, _CurrentSolution);
            solutionStream.Close();
            foreach (Project project in _CurrentSolution.Projects)
            {
                if (File.Exists(CurrentSolutionDirectory + "\\" + project.RootDirectory + "\\" + project.Name + ".tiproj"))
                    File.Delete(CurrentSolutionDirectory + "\\" + project.RootDirectory + "\\" + project.Name + ".tiproj");
                Stream projectStream = File.Create(CurrentSolutionDirectory + "\\" + project.RootDirectory + "\\" + project.Name + ".tiproj");
                format.Serialize(projectStream, project);
                projectStream.Close();
            }
        }

        void Explorer_NewFileRequested(object sender, NewFileEventArgs e)
        {
            //TODO add checks for when there isn't a solution or project selected
            CreateFileDialog dialog = new CreateFileDialog(CurrentSolutionDirectory + "\\" + e.Project.RootDirectory,
                _CurrentSolution.Language);
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                OpenCodeWindow(dialog.FileName);
                int projectIndex = _CurrentSolution.Projects.IndexOf(e.Project);
                _CurrentSolution.Projects[projectIndex].Files.Add(DataConverter.StripDirectory(dialog.FileName));
                BinaryFormatter format = new BinaryFormatter();
                StreamWriter writer = new StreamWriter(CurrentSolutionFile);
                format.Serialize(writer.BaseStream, _CurrentSolution);
                writer.Close();
                Explorer.UpdateSolution(_CurrentSolution);
                SaveSolutionAndProjects();
            }
        }

        void Explorer_OpenFileRequested(object sender, FileActionEventArgs e)
        {
            OpenCodeWindow(CurrentSolutionDirectory + e.File);
        }

        private void SetUpUserFolder()
        {
            string documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            if (!Directory.Exists(documents + "\\tiDE"))
                Directory.CreateDirectory(documents + "\\tiDE");
            if (!Directory.Exists(documents + "\\tiDE\\Projects"))
                Directory.CreateDirectory(documents + "\\tiDE\\Projects");
            if (!Directory.Exists(documents + "\\tiDE\\Settings"))
                Directory.CreateDirectory(documents + "\\tiDE\\Settings");
            if (!Directory.Exists(documents + "\\tiDE\\Templates"))
                Directory.CreateDirectory(documents + "\\tiDE\\Templates");
            if (!Directory.Exists(documents + "\\tiDE\\Templates\\FileTemplates"))
                Directory.CreateDirectory(documents + "\\tiDE\\Templates\\FileTemplates");
            RuntimeData.tiDEUserDirectory = documents + "\\tiDE";
        }

        void page_OpenProject(object sender, EventArgs e)
        {
            openFileDialog1.Title = "Open Solution";
            openFileDialog1.Filter = "tiDE Solutions (*.tisln)|*.tisln";
            if (openFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            BinaryFormatter format = new BinaryFormatter();
            StreamReader reader = new StreamReader(openFileDialog1.FileName);
            CurrentSolution = (Solution)format.Deserialize(reader.BaseStream);
            CloseAllWindows();
            reader.Close();
            CurrentSolutionFile = openFileDialog1.FileName;
            CurrentSolutionDirectory = DataConverter.GetDirectoryFromFile(CurrentSolutionFile);
            List<string> newOpenFiles = new List<string>();
            foreach (string file in CurrentSolution.OpenFiles)
            {
                if (File.Exists(CurrentSolutionDirectory + file))
                {
                    OpenCodeWindow(CurrentSolutionDirectory + file);
                    newOpenFiles.Add(file);
                }
            }
            _CurrentSolution.OpenFiles = newOpenFiles;
            ProjectLayout();
            Explorer.UpdateSolution(_CurrentSolution);
            if (GlobalSettings.RecentSolutions.Contains(openFileDialog1.FileName))
                GlobalSettings.RecentSolutions.Remove(openFileDialog1.FileName);
            GlobalSettings.RecentSolutions.Add(openFileDialog1.FileName);
            SaveGlobalSettings();
        }

        void dockPanel1_ActiveContentChanged(object sender, EventArgs e)
        {
            if (dockPanel1.ActiveDocument is CodeWindow)
                EditLayout();
            else
                NormalLayout();
        }

        void ProjectLayout()
        {
            saveToolStripMenuItem1.Enabled = true;
            saveAllToolStripMenuItem.Enabled = true;
            saveAsToolStripMenuItem.Enabled = true;
            saveAsTemplateToolStripMenuItem.Enabled = true;
            solutionExplorerToolStripMenuItem.Enabled = true;
            findAndReplaceToolStripMenuItem.Enabled = true;
            rebuildProjectToolStripMenuItem.Enabled = true;
            buildProjectToolStripMenuItem.Enabled = true;
            buildProjectToolStripMenuItem1.Enabled = true;
            buildProjectToolStripMenuItem2.Enabled = true;
            startDebuggingToolStripMenuItem.Enabled = true;
            debugToolStripMenuItem.Enabled = true;
            startWithoutDebuggerToolStripMenuItem.Enabled = true;
            closeSolutionToolStripMenuItem.Enabled = true;
            outputToolStripMenuItem.Enabled = true;
            errorsToolStripMenuItem.Enabled = true;
            //outputWindow = new Output();
            //errors = new ErrorWindow();
            //Explorer = new SolutionExplorer();
            outputWindow.Show(dockPanel1, DockState.DockBottomAutoHide);
            errors.Show(dockPanel1, DockState.DockBottomAutoHide);
            Explorer.Show(dockPanel1, DockState.DockRightAutoHide);
        }

        void ProjectClosedLayout()
        {
            saveToolStripMenuItem.Enabled = true;
            saveAllToolStripMenuItem.Enabled = true;
            saveAsToolStripMenuItem.Enabled = true;
            saveAsTemplateToolStripMenuItem.Enabled = true;
            solutionExplorerToolStripMenuItem.Enabled = false;
            findAndReplaceToolStripMenuItem.Enabled = false;
            rebuildProjectToolStripMenuItem.Enabled = false;
            buildProjectToolStripMenuItem.Enabled = false;
            buildProjectToolStripMenuItem1.Enabled = false;
            buildProjectToolStripMenuItem2.Enabled = false;
            startDebuggingToolStripMenuItem.Enabled = false;
            debugToolStripMenuItem.Enabled = false;
            startWithoutDebuggerToolStripMenuItem.Enabled = false;
            closeSolutionToolStripMenuItem.Enabled = false;
            outputToolStripMenuItem.Enabled = false;
            errorsToolStripMenuItem.Enabled = false;
        }

        void EditLayout()
        {
            printToolStripButton.Enabled = true;
            printToolStripMenuItem.Enabled = true;
            copyToolStripButton.Enabled = true;
            copyToolStripMenuItem.Enabled = true;
            cutToolStripButton.Enabled = true;
            cutToolStripMenuItem.Enabled = true;
            pasteToolStripButton.Enabled = true;
            pasteToolStripMenuItem.Enabled = true;
            selectAllToolStripMenuItem.Enabled = true;
            undoToolStripMenuItem.Enabled = true;
            redoToolStripMenuItem.Enabled = true;
            saveToolStripMenuItem.Enabled = true;
            saveAllToolStripMenuItem.Enabled = true;
            saveAsTemplateToolStripMenuItem.Enabled = true;
            saveAsToolStripMenuItem.Enabled = true;
        }

        void NormalLayout()
        {
            printToolStripButton.Enabled = false;
            printToolStripMenuItem.Enabled = false;
            copyToolStripButton.Enabled = false;
            copyToolStripMenuItem.Enabled = false;
            cutToolStripButton.Enabled = false;
            cutToolStripMenuItem.Enabled = false;
            pasteToolStripButton.Enabled = false;
            pasteToolStripMenuItem.Enabled = false;
            selectAllToolStripMenuItem.Enabled = false;
            undoToolStripMenuItem.Enabled = false;
            redoToolStripMenuItem.Enabled = false;
            saveToolStripMenuItem.Enabled = false;
            saveAllToolStripMenuItem.Enabled = false;
            saveAsTemplateToolStripMenuItem.Enabled = false;
            saveAsToolStripMenuItem.Enabled = false;
        }

        private void CloseAllWindows()
        {
            // TODO: Make this less hacky
            List<IDockContent> ContentToClose = new List<IDockContent>();
            foreach (IDockContent window in dockPanel1.Contents)
            {
                ContentToClose.Add(window);
            }
            while (ContentToClose.Count != 0)
            {
                (dockPanel1.Contents[dockPanel1.Contents.IndexOf(ContentToClose[0])] as Form).Close();
                ContentToClose.RemoveAt(0);
            }
            this.Invalidate(true);
        }

        private void tiDEWindow_Resize(object sender, EventArgs e)
        {
            this.Invalidate(true);
        }

        private void tiDEWindow_Load(object sender, EventArgs e)
        {
            // This maximizes the window on start
            this.WindowState = FormWindowState.Maximized;
        }

        private void OpenCodeWindow(string CodeFile)
        {
            // See if that file is already open and simply give it focus
            foreach (IDockContent content in dockPanel1.Contents)
            {
                if (content is CodeWindow)
                {
                    if ((content as CodeWindow).CodeFile == CodeFile)
                    {
                        (content as CodeWindow).Select();
                        return;
                    }
                }
            }
            if (!File.Exists(CodeFile))
            {
                MessageBox.Show("Unable to open " + DataConverter.StripDirectory(CodeFile) + ": File not found",
                    "File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            CodeWindow codeWindow;
            if (CurrentSolution == null)
                codeWindow = new CodeWindow(CodeFile, this);
            else
            {	//Added to deal with the opening of a file when there isn't
                //a project or solution open
                codeWindow = new CodeWindow(CodeFile, this);
                foreach (Project project in _CurrentSolution.Projects)
                {
                    foreach (string file in project.Files)
                    {
                        if (CurrentSolutionDirectory + project.RootDirectory + "\\" + file == CodeFile)
                        {
                            if (!_CurrentSolution.OpenFiles.Contains(project.RootDirectory + "\\" + file))
                                _CurrentSolution.OpenFiles.Add(project.RootDirectory + "\\" + file);
                            SaveSolutionAndProjects();
                            break;
                        }
                    }
                }
            }
            codeWindow.Show(dockPanel1, DockState.Document);
        }

        private void PopulateErrorPanel(AssemblyOutput Output, string File)
        {
            foreach (AssemblerError Error in Output.Errors)
            {
                ListViewItem item = new ListViewItem("");
                item.ImageIndex = 0;
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.Type.ToString()));
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.UserMessage));
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.Line.ToString()));
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.IndexOf.ToString()));
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, File));
                AddErrorItemAsync(item);
                outputWindow.WriteLine("    Error: " + Error.Line.ToString() + ", " + Error.IndexOf.ToString() +
                    ": " + Error.Type.ToString() + ": " + Error.UserMessage);
            }
        }

        private void PopulateErrorPanel(LinkerOutput Output, string File)
        {
            foreach (LinkError Error in Output.Errors)
            {
                ListViewItem item = new ListViewItem("");
                item.ImageIndex = 0;
                //item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.Type.ToString()));
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.Message));
                //item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.Line.ToString()));
                //item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Error.IndexOf.ToString()));
                item.SubItems.Add(new ListViewItem.ListViewSubItem(item, File));
                AddErrorItemAsync(item);
                //outputWindow.WriteLine("    Error: " + Error.Line.ToString() + ", " + Error.IndexOf.ToString() +
                //    ": " + Error.Type.ToString() + ": " + Error.UserMessage);
            }
        }

        delegate void AddErrorItemDelegate(ListViewItem item);
        private void AddErrorItemAsync(ListViewItem item)
        {
            if (this.InvokeRequired)
            {
                AddErrorItemDelegate invokeDelegate = new AddErrorItemDelegate(AddErrorItemAsync);
                this.Invoke(invokeDelegate, new object[] { item });
            }
            else
            {
                errors.listView1.Items.Add(item);
            }
        }

        delegate void ClearErrorsDelegate();
        private void ClearErrorsAsync()
        {
            if (this.InvokeRequired)
            {
                ClearErrorsDelegate invokeDelegate = new ClearErrorsDelegate(ClearErrorsAsync);
                this.Invoke(invokeDelegate);
            }
            else
            {
                errors.listView1.Items.Clear();
            }
        }

        private void buildProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Build();
        }

        private void parseShortcuts(object sender, KeyEventArgs e)
        {
            toolStripStatusLabel1.Text = "Ready";
            KeyboardShortcut shortcut = new KeyboardShortcut()
            {
                IsShift = e.Shift,
                IsAlt = e.Alt,
                IsControl = e.Control,
                Key = e.KeyCode,
            };
            shortcut = GlobalSettings.ShortcutManager.GetByShortcut(shortcut);
            if (shortcut == null)
                return;
            e.SuppressKeyPress = true;
            ToolStripMenuItem parentItem = null;
            foreach (ToolStripMenuItem subItem in menuStrip1.Items)
                if (subItem.Text == shortcut.MenuPath[0])
                {
                    parentItem = subItem;
                    break;
                }
            if (parentItem == null)
                return;
            ToolStripDropDownItem dropDownItem = null;
            for (int i = 0; i < parentItem.DropDownItems.Count; i++)
            {
                ToolStripDropDownItem subItem = parentItem.DropDownItems[i] as ToolStripDropDownItem;
                if (subItem == null)
                    continue;
                if (subItem.Text == shortcut.MenuPath[1])
                {
                    dropDownItem = subItem;
                    break;
                }
            }
            if (dropDownItem == null)
                return;
            for (int i = 2; i < shortcut.MenuPath.Length; i++)
            {
                for (int j = 0; j < dropDownItem.DropDownItems.Count; j++)
                {
                    ToolStripDropDownItem subItem = dropDownItem.DropDownItems[j] as ToolStripDropDownItem;
                    if (subItem == null)
                        continue;
                    if (subItem.Text == shortcut.MenuPath[i])
                    {
                        dropDownItem = subItem;
                        break;
                    }
                }
            }
            if (dropDownItem == null)
                return;
            dropDownItem.PerformClick();
        }

        private void SaveCurrentDocument()
        {
            // The next line is a comment for personal debugging purposes
            (dockPanel1.ActiveDocument as CodeWindow).Save();
            Explorer.UpdateSolution(_CurrentSolution);
        }

        private void SaveAllDocuments()
        {
            foreach (DockContent content in dockPanel1.Documents)
            {
                if (content.GetType() == typeof(CodeWindow))
                {
                    (content as CodeWindow).Save();
                }
            }
            Explorer.UpdateSolution(_CurrentSolution);
        }

        bool IsBuilding = false;

        private void Build()
        {
            if (IsBuilding)
                return;
            IsBuilding = true;
            outputWindow.Clear();
            outputWindow.WriteLine("Build started...");
            outputWindow.Show();
            SaveAllDocuments();
            toolStripStatusLabel1.Text = "Build started...";
            ThreadStart thread = new ThreadStart(BuildSecondaryThread);
            thread.BeginInvoke(BuildThreadDone, null);
        }

        void BuildThreadDone(IAsyncResult result)
        {
            if (!BuildFinished)
            {
                PopulateErrorPanel(new AssemblyOutput()
                {
                    Errors = new List<AssemblerError>(new AssemblerError[]
                    {
                        new AssemblerError()
                        {
                            UserMessage = "The assembler appears to have crashed.",
                        }
                    }),
                }, "");
                BuildFailedInvoke();
            }
            IsBuilding = false;
        }

        delegate void BuildDoneInvokeDelegate();

        void BuildDoneInvoke()
        {
            if (this.InvokeRequired)
            {
                BuildDoneInvokeDelegate invokeDelegate = new BuildDoneInvokeDelegate(BuildDoneInvoke);
                this.Invoke(invokeDelegate);
            }
            else
            {
                outputWindow.WriteLine("Build complete.");
                toolStripStatusLabel1.Text = "Build complete.";
                IsBuilding = false;
            }
        }

        delegate void BuildFailedInvokeDelegate();

        void BuildFailedInvoke()
        {
            if (this.InvokeRequired)
            {
                BuildFailedInvokeDelegate invokeDelegate = new BuildFailedInvokeDelegate(BuildFailedInvoke);
                this.Invoke(invokeDelegate);
            }
            else
            {
                outputWindow.WriteLine("Build failed.");
                toolStripStatusLabel1.Text = "Build failed.";
                IsBuilding = false;
                errors.Show();
            }
        }

        bool BuildFinished = false;

        void BuildSecondaryThread()
        {
            DateTime buildStart = DateTime.Now;
            BuildFinished = false;
            if (CurrentSolution.Language == "z80")
            {
                ClearErrorsAsync();
                Assembler asm = new Assembler();
                Linker link = new Linker();
                StreamReader reader;
                bool success = true;
                foreach (Project project in CurrentSolution.Projects)
                {
                    outputWindow.WriteLine(" Compiling " + project.Name);
                    List<AssemblyOutput> outputs = new List<AssemblyOutput>();
                    bool successIndividual = true;
                    foreach (string file in project.Files)
                    {
                        if (!File.Exists(DataConverter.GetDirectoryFromFile(CurrentSolutionFile) + "\\" +
                            project.RootDirectory + "\\" + DataConverter.StripDirectory(file)))
                        {
                            outputWindow.WriteLine("Warning: Unable to open " + file);
                            continue;
                        }
                        outputWindow.WriteLine("  Assembling " + file);
                        string source;
                        lock (saveFilesLock)
                        {
                            reader = new StreamReader(DataConverter.GetDirectoryFromFile(CurrentSolutionFile) + "\\" +
                                project.RootDirectory + "\\" + DataConverter.StripDirectory(file));
                            source = reader.ReadToEnd();
                            reader.Close();
                        }
                        AssemblyOutput asmOutput = asm.Assemble(source,
                            DataConverter.GetDirectoryFromFile(CurrentSolutionFile) + "\\" + project.RootDirectory + "\\",
                            DataConverter.GetDirectoryFromFile(CurrentSolutionFile) + "\\" + project.RootDirectory + "\\" + file);
                        outputs.Add(asmOutput);
                        if (asmOutput.Errors.Count != 0)
                        {
                            success = false;
                            successIndividual = false;
                            outputWindow.WriteLine("  Assembly failed");
                        }
                        PopulateErrorPanel(asmOutput, file);
                    }
                    if (!successIndividual)
                        break;
                    outputWindow.WriteLine(" Linking " + project.Name);
                    LinkerOutput linkOutput = link.Link(outputs);
                    byte[] output = linkOutput.FinalOutput;
                    PopulateErrorPanel(linkOutput, project.Name);
                    if (linkOutput.Errors.Count != 0)
                    {
                        success = false;
                        break;
                    }
                    outputWindow.WriteLine(" Packing " + project.Type);
                    IPacker packer = (IPacker)Activator.CreateInstance(InstalledPackers[project.Packer]);
                    packer.Pack(output, project, CurrentSolutionDirectory + project.RootDirectory + "\\" +
                            project.Name.Replace(" ", "") + "." + packer.OutputExtention);
                }
                if (success)
                    BuildDoneInvoke();
                else
                    BuildFailedInvoke();
                TimeSpan duration = DateTime.Now - buildStart;
                outputWindow.WriteLine("Build duration: " + duration.Minutes + ":" + duration.Seconds + "." + duration.Milliseconds);
            }
            else if (CurrentSolution.Language == "C")
            {
                //foreach (Project project in CurrentSolution.Projects)
                //GCCBridge.Compile(project, CurrentSolutionDirectory);
                PopulateErrorPanel(new AssemblyOutput()
                {
                    Errors = new List<AssemblerError>(new AssemblerError[]
                    {
                        new AssemblerError()
                        {
                            UserMessage = "C compilation is not yet supported",
                        },
                    }),
                }, "");
            }
            else if (CurrentSolution.Language == "TIBasic" || CurrentSolution.Language == "Axe")
            {
                Tokenizer tokenizer = new Tokenizer();
                StreamReader reader;
                foreach (Project project in CurrentSolution.Projects)
                {
                    foreach (string file in project.Files)
                    {
                        string source;
                        lock (saveFilesLock)
                        {
                            reader = new StreamReader(DataConverter.GetDirectoryFromFile(CurrentSolutionFile) + "\\" +
                                project.RootDirectory + "\\" + DataConverter.StripDirectory(file));
                            source = reader.ReadToEnd();
                            reader.Close();
                        }
                        TokenizerOutput output = tokenizer.Tokenize(source);
                        if (output.Success)
                        {
                            Program83PlusProjectData data = project.Tag as Program83PlusProjectData;
                            DataConverter.Save8xp(false, output.Output, data.OnCalcName, CurrentSolutionDirectory + project.RootDirectory + "\\" +
                                project.Name.Replace(" ", "") + ".8xp");
                            BuildDoneInvoke();
                        }
                        else
                            BuildFailedInvoke();
                    }
                }
            }
            BuildFinished = true;
        }

        object saveFilesLock = new object();

        private string GetHexString(byte[] input)
        {
            string value = "";
            foreach (byte b in input)
            {
                string hex = b.ToString("x");
                if (hex.Length == 1)
                    hex = "0" + hex;
                value += hex;
            }
            return value.ToUpper();
        }

        private void Debug()
        {
            Build();
            tIOSToolStripMenuItem_Click(this, new EventArgs());
        }

        private void StartWithoutDebugging()
        {
            Build();
        }

        private void openToolStripButton_Click(object sender, EventArgs e)
        {
            openFileDialog1.FileName = "";
            openFileDialog1.Filter = GenericFilter;
            if (openFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            OpenCodeWindow(openFileDialog1.FileName);
        }

        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            SaveCurrentDocument();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            Build();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            Debug();
        }

        private void newProject(object sender, EventArgs e)
        {
            // TODO: More information in the output window
            CreateProjectDialog Dialog = new CreateProjectDialog();
            if (Dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            CurrentSolution = Dialog.Solution;
            CurrentSolutionFile = Dialog.SolutionFile;
            CurrentSolutionDirectory = DataConverter.GetDirectoryFromFile(CurrentSolutionFile);
            CloseAllWindows();
            List<string> newOpenFiles = new List<string>();
            foreach (string file in CurrentSolution.OpenFiles)
            {
                if (File.Exists(CurrentSolutionDirectory + file))
                {
                    OpenCodeWindow(CurrentSolutionDirectory + file);
                    newOpenFiles.Add(file);
                }
            }
            _CurrentSolution.OpenFiles = newOpenFiles;
            ProjectLayout();
            Explorer.UpdateSolution(_CurrentSolution);
            if (GlobalSettings.RecentSolutions.Contains(CurrentSolutionFile))
                GlobalSettings.RecentSolutions.Remove(CurrentSolutionFile);
            GlobalSettings.RecentSolutions.Add(CurrentSolutionFile);
            SaveGlobalSettings();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // This will open the About Box
            AboutBox about = new AboutBox();
            about.ShowDialog();
        }

        private void buildProjectToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Build();
        }

        private void closeSolutionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CurrentSolutionFile = "";
            CurrentSolution = null;
            NormalLayout();
        }

        private void errorsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            errors = new ErrorWindow();
            errors.Show(dockPanel1, DockState.Document);

        }

        private void solutionExplorerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Explorer.Show(dockPanel1, DockState.Document);
        }

        private void outputToolStripMenuItem_Click(object sender, EventArgs e)
        {
            outputWindow = new OutputWindow();
            outputWindow.Show(dockPanel1, DockState.Document);
        }

        private void startPageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StartPage startPage = new StartPage();
            startPage.OpenProject += new EventHandler(page_OpenProject);
            startPage.RecentProjectSelected += new EventHandler<OpenProjectArgs>(page_RecentProjectSelected);
            startPage.NewProject += new EventHandler(newProject);
            startPage.Show(dockPanel1, DockState.Document);
        }

        private void dCS7DesignerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DCSGUIDesigner designer = new DCSGUIDesigner();
            designer.Show(dockPanel1, DockState.Document);
        }

        private void forumsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.omnimaga.org/index.php?board=126.0");
        }

        private void optionsToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            GlobalSettingEditor settingsEditor = new GlobalSettingEditor();
            settingsEditor.ShowDialog();
            SaveGlobalSettings();
        }

        private void spriteEditorToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            SpriteEdit spriteEditor = new SpriteEdit();
            spriteEditor.Show(dockPanel1, DockState.Document);
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {

        }

        private void tiDEWindow_MouseMove(object sender, MouseEventArgs e)
        {

        }

        //Stetson.Stetson stetson;
        //Stetson.Keyboard emulatorKeyboard;

        List<Stetson.Stetson> emulators = new List<Stetson.Stetson>();
        List<Stetson.Keyboard> emulatorKeyboards = new List<Stetson.Keyboard>();

        private void tIOSToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stetson.Stetson stetson = new Stetson.Stetson(GlobalSettings.ROM83Plus);
            if (emulators.Count == 0)
                stetson.Show(dockPanel1, DockState.DockRight);
            else
                stetson.Show(dockPanel1, DockState.Float);
            Stetson.Keyboard emulatorKeyboard = new Stetson.Keyboard();
            emulatorKeyboard.EmulatorKeyDown += new EventHandler<Stetson.EmulatorKeyEventArgs>(emulatorKeyboard_EmulatorKeyDown);
            emulatorKeyboard.EmulatorKeyUp += new EventHandler<Stetson.EmulatorKeyEventArgs>(emulatorKeyboard_EmulatorKeyUp);
            emulatorKeyboard.KeyDown += new System.Windows.Forms.KeyEventHandler(emulatorKeyboard_KeyDown);
            emulatorKeyboard.KeyUp += new System.Windows.Forms.KeyEventHandler(emulatorKeyboard_KeyUp);
            stetson.Tag = emulatorKeyboard;
            emulatorKeyboard.Tag = stetson;
            if (emulators.Count == 0)
                emulatorKeyboard.Show(stetson.Pane, DockAlignment.Bottom, .7);
            else
                emulatorKeyboard.Show(dockPanel1, DockState.Float);
            foreach (Stetson.Stetson emulator in emulators)
            {
                emulator.calculator.LinkEmulator(stetson.calculator);
            }
            emulators.Add(stetson);
            emulatorKeyboards.Add(emulatorKeyboard);
        }

        private void selectROMToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stetson.Stetson stetson = new Stetson.Stetson();
            if (emulators.Count == 0)
                stetson.Show(dockPanel1, DockState.DockRight);
            else
                stetson.Show(dockPanel1, DockState.Float);
            Stetson.Keyboard emulatorKeyboard = new Stetson.Keyboard();
            emulatorKeyboard.EmulatorKeyDown += new EventHandler<Stetson.EmulatorKeyEventArgs>(emulatorKeyboard_EmulatorKeyDown);
            emulatorKeyboard.EmulatorKeyUp += new EventHandler<Stetson.EmulatorKeyEventArgs>(emulatorKeyboard_EmulatorKeyUp);
            emulatorKeyboard.KeyDown += new System.Windows.Forms.KeyEventHandler(emulatorKeyboard_KeyDown);
            emulatorKeyboard.KeyUp += new System.Windows.Forms.KeyEventHandler(emulatorKeyboard_KeyUp);
            stetson.Tag = emulatorKeyboard;
            emulatorKeyboard.Tag = stetson;
            if (emulators.Count == 0)
                emulatorKeyboard.Show(stetson.Pane, DockAlignment.Bottom, .7);
            else
                emulatorKeyboard.Show(dockPanel1, DockState.Float);
            stetson.FormClosing += new FormClosingEventHandler(stetson_FormClosing);
            emulatorKeyboard.FormClosing += new FormClosingEventHandler(emulatorKeyboard_FormClosing);
            foreach (Stetson.Stetson emulator in emulators)
            {
                emulator.calculator.LinkEmulator(stetson.calculator);
            }
            emulators.Add(stetson);
            emulatorKeyboards.Add(emulatorKeyboard);
        }

        void emulatorKeyboard_FormClosing(object sender, FormClosingEventArgs e)
        {
            emulatorKeyboards.Remove((Stetson.Keyboard)sender);
        }

        void stetson_FormClosing(object sender, FormClosingEventArgs e)
        {
            emulators.Remove((Stetson.Stetson)sender);
            foreach (Stetson.Stetson stetson in emulators)
            {
                stetson.calculator.UnlinkEmulator(((Stetson.Stetson)sender).calculator);
            }
        }

        void emulatorKeyboard_KeyUp(object sender, KeyEventArgs e)
        {
            ((sender as Stetson.Keyboard).Tag as Stetson.Stetson).Stetson_KeyUp(sender, e);
        }

        void emulatorKeyboard_KeyDown(object sender, KeyEventArgs e)
        {
            ((sender as Stetson.Keyboard).Tag as Stetson.Stetson).Stetson_KeyDown(sender, e);
        }

        void emulatorKeyboard_EmulatorKeyUp(object sender, Stetson.EmulatorKeyEventArgs e)
        {
            ((sender as Stetson.Keyboard).Tag as Stetson.Stetson).EmulatorKeyUp(e.Keyname);
        }

        void emulatorKeyboard_EmulatorKeyDown(object sender, Stetson.EmulatorKeyEventArgs e)
        {
            ((sender as Stetson.Keyboard).Tag as Stetson.Stetson).EmulatorKeyDown(e.Keyname);
        }

        private void contextMenuStrip1_Opening_1(object sender, CancelEventArgs e)
        {

        }

        private void closeToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (dockPanel1.ActiveDocument is CodeWindow)
            {
                string file = (dockPanel1.ActiveDocument as CodeWindow).CodeFile;
                if (CurrentSolutionDirectory != null)
                {
                    file = file.Replace(CurrentSolutionDirectory, "");
                    //added support for documents that aren't in projects/solutions
                    if (file != null)
                    {
                        file = file.Replace(CurrentSolutionDirectory, "");
                        if (_CurrentSolution != null)
                        {
                            if (_CurrentSolution.OpenFiles.Contains(file))
                                _CurrentSolution.OpenFiles.Remove(file);
                            SaveSolutionAndProjects();
                        }
                    }
                }
            }
            dockPanel1.ActiveDocument.DockHandler.Close();
        }

        private void findAndReplaceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FindAndReplace fAndR = new FindAndReplace();
            fAndR.AllowEndUserDocking = false;
            fAndR.ActionRequested += new EventHandler<FindAndReplaceEventArgs>(fAndR_ActionRequested);
            fAndR.Show(dockPanel1, DockState.Float);
        }

        void fAndR_ActionRequested(object sender, FindAndReplaceEventArgs e)
        {
            if (!(dockPanel1.ActiveDocument is CodeWindow))
                return;
            if (e.FindText == e.ReplaceText)
                return;
            switch (e.Action)
            {
                case FindAndReplaceAction.Replace:
                    if (e.UseRegex)
                    {
                        Regex regex = null;
                        if (e.MatchCase)
                            regex = new Regex(e.FindText, RegexOptions.CultureInvariant | RegexOptions.Multiline);
                        else
                            regex = new Regex(e.FindText, RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.IgnoreCase);
                        Match match = regex.Match((dockPanel1.ActiveDocument as CodeWindow).Code,
                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                        if (!match.Success)
                        {
                            match = regex.Match((dockPanel1.ActiveDocument as CodeWindow).Code);
                            toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                        }

                        if (!match.Success)
                        {
                            MessageBox.Show("The following text was not found:\n" + e.FindText);
                            return;
                        }

                        TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(match.Index);

                        (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Remove(match.Index, match.Length);
                        (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Insert(match.Index, e.ReplaceText);

                        (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;

                        (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                            foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(match.Index + e.ReplaceText.Length));

                        (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                    }
                    else
                    {
                        if (e.MatchCase)
                        {
                            if (!(dockPanel1.ActiveDocument as CodeWindow).Code.Contains(e.FindText))
                            {
                                MessageBox.Show("The following text was not found:\n" + e.FindText);
                                return;
                            }

                            int index = (dockPanel1.ActiveDocument as
                                CodeWindow).Code.IndexOf(e.FindText,
                                (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                            if (index == -1)
                            {
                                index = (dockPanel1.ActiveDocument as CodeWindow).Code.IndexOf(e.FindText);
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                            }

                            TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);

                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Remove(index, e.FindText.Length);
                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Insert(index, e.ReplaceText);

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                                foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + e.ReplaceText.Length));

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                        }
                        else
                        {
                            if (!(dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().Contains(e.FindText.ToLower()))
                            {
                                MessageBox.Show("The following text was not found:\n" + e.FindText);
                                return;
                            }

                            int index = (dockPanel1.ActiveDocument as
                                CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower(),
                                (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                            if (index == -1)
                            {
                                index = (dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower());
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                            }

                            TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);

                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Remove(index, e.FindText.Length);
                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Insert(index, e.ReplaceText);

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                                foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + e.ReplaceText.Length));

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                        }
                    }
                    break;
                case FindAndReplaceAction.ReplaceAll:
                    if (e.UseRegex)
                    {
                        Regex regex = null;
                        if (e.MatchCase)
                            regex = new Regex(e.FindText, RegexOptions.CultureInvariant | RegexOptions.Multiline);
                        else
                            regex = new Regex(e.FindText, RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.IgnoreCase);
                        Match match = regex.Match((dockPanel1.ActiveDocument as CodeWindow).Code);

                        if (!match.Success)
                        {
                            MessageBox.Show("The following text was not found:\n" + e.FindText);
                            return;
                        }

                        TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(match.Index);

                        while (match.Success)
                        {
                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Remove(match.Index, match.Length);
                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Insert(match.Index, e.ReplaceText);
                            match = regex.Match((dockPanel1.ActiveDocument as CodeWindow).Code);
                        }
                    }
                    else
                    {
                        if (e.MatchCase)
                        {
                            if (!(dockPanel1.ActiveDocument as CodeWindow).Code.Contains(e.FindText))
                            {
                                MessageBox.Show("The following text was not found:\n" + e.FindText);
                                return;
                            }

                            int index = (dockPanel1.ActiveDocument as
                                CodeWindow).Code.IndexOf(e.FindText,
                                (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                            if (index == -1)
                            {
                                index = (dockPanel1.ActiveDocument as CodeWindow).Code.IndexOf(e.FindText);
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                            }

                            TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);

                            (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Replace(e.FindText, e.ReplaceText);
                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                                foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + e.ReplaceText.Length));

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                        }
                        else
                        {
                            if (!(dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().Contains(e.FindText.ToLower()))
                            {
                                MessageBox.Show("The following text was not found:\n" + e.FindText);
                                return;
                            }

                            int index = (dockPanel1.ActiveDocument as
                                CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower(),
                                (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                            if (index == -1)
                            {
                                index = (dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower());
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                            }

                            TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);

                            while ((dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().Contains(e.FindText.ToLower()))
                            {
                                int currentIndex = (dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower());
                                (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Remove(currentIndex, e.FindText.Length);
                                (dockPanel1.ActiveDocument as CodeWindow).Code = (dockPanel1.ActiveDocument as CodeWindow).Code.Insert(currentIndex, e.ReplaceText);
                            }

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                                foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + e.ReplaceText.Length));

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                        }
                    }
                    break;

                case FindAndReplaceAction.FindNext:
                    if (e.UseRegex)
                    {
                        // Regex
                        Regex regex = null;
                        if (!e.MatchCase)
                            regex = new Regex(e.FindText, RegexOptions.Multiline | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
                        else
                            regex = new Regex(e.FindText, RegexOptions.Multiline | RegexOptions.CultureInvariant);

                        Match match = regex.Match((dockPanel1.ActiveDocument as CodeWindow).Code.ToLower(),
                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                        if (!match.Success)
                        {
                            match = regex.Match((dockPanel1.ActiveDocument as CodeWindow).Code.ToLower());
                            if (match.Success)
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                        }

                        if (!match.Success)
                        {
                            MessageBox.Show("The following regular expression was not matched:\n" + e.FindText);
                            return;
                        }

                        int index = match.Index;

                        TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);

                        (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;
                        (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                            foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + match.Length));

                        (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                    }
                    else
                    {
                        // Non-regex
                        if (!e.MatchCase)
                        {
                            if (!(dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().Contains(e.FindText.ToLower()))
                            {
                                MessageBox.Show("The following text was not found:\n" + e.FindText);
                                return;
                            }
                            int index = (dockPanel1.ActiveDocument as
                                CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower(),
                                (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                            if (index == -1)
                            {
                                index = (dockPanel1.ActiveDocument as CodeWindow).Code.ToLower().IndexOf(e.FindText.ToLower());
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                            }

                            TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);


                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;
                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                                foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + e.FindText.Length));

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                        }
                        else
                        {
                            if (!(dockPanel1.ActiveDocument as CodeWindow).Code.Contains(e.FindText))
                            {
                                MessageBox.Show("The following text was not found:\n" + e.FindText);
                                return;
                            }

                            int index = (dockPanel1.ActiveDocument as
                                CodeWindow).Code.IndexOf(e.FindText,
                                (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Offset + 1);

                            if (index == -1)
                            {
                                index = (dockPanel1.ActiveDocument as CodeWindow).Code.IndexOf(e.FindText);
                                toolStripStatusLabel1.Text = "Reached end of document, continuing from start";
                            }

                            TextLocation foundText = (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index);


                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.Caret.Position = foundText;
                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.TextArea.SelectionManager.SetSelection(
                                foundText, (dockPanel1.ActiveDocument as CodeWindow).TextEdit.Document.OffsetToPosition(index + e.FindText.Length));

                            (dockPanel1.ActiveDocument as CodeWindow).TextEdit.ActiveTextAreaControl.ScrollToCaret();
                        }
                    }
                    break;
            }
        }

        private void addToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            CreateCustomToolDialog dialog = new CreateCustomToolDialog();
            if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            CustomTool tool = new CustomTool()
            {
                Name = dialog.textBox1.Text,
                FileName = dialog.textBox2.Text,
                Arguments = dialog.textBox3.Text,
            };
            GlobalSettings.CustomTools.Add(tool);
            SaveGlobalSettings();
            UpdateCustomTools();
        }

        private void UpdateCustomTools()
        {
            while (externalToolsToolStripMenuItem.DropDownItems.Count != 2)
                externalToolsToolStripMenuItem.DropDownItems.RemoveAt(2);
            foreach (CustomTool tool in GlobalSettings.CustomTools)
            {
                ToolStripMenuItem item = new ToolStripMenuItem(tool.Name);
                item.Tag = tool;
                item.Click += new EventHandler(item_Click);
                externalToolsToolStripMenuItem.DropDownItems.Add(item);
            }
        }

        void item_Click(object sender, EventArgs e)
        {
            try
            {
                CustomTool tool = (sender as ToolStripDropDownItem).Tag as CustomTool;
                ProcessStartInfo info = new ProcessStartInfo(tool.FileName, ParseProjectSyntax(tool.Arguments));
                info.WorkingDirectory = DataConverter.GetDirectoryFromFile(tool.FileName);
                Process.Start(info);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        string ParseProjectSyntax(string Text)
        {
            if (Text.Contains("{OpenFile}"))
            {
                if (dockPanel1.ActiveDocument is CodeWindow)
                {
                    Text = Text.Replace("{OpenFile}", (dockPanel1.ActiveDocument as CodeWindow).CodeFile);
                }
                else
                {
                    MessageBox.Show("No file is open!");
                }
            }
            if (Text.Contains("{ProjectFile}"))
            {
                if (dockPanel1.ActiveDocument is CodeWindow)
                {
                    foreach (Project proj in _CurrentSolution.Projects)
                    {
                        bool shouldBreak = false;
                        foreach (string file in proj.Files)
                        {
                            if (CurrentSolutionDirectory + proj.RootDirectory + "\\" + file == (dockPanel1.ActiveDocument as CodeWindow).Code)
                            {
                                Text = Text.Replace("{ProjectFile}", CurrentSolutionDirectory + proj.RootDirectory + "\\" +
                                    proj.Name + ".tiproj");
                                shouldBreak = true;
                                break;
                            }
                        }
                        if (shouldBreak)
                            break;
                    }
                }
                else
                {
                    MessageBox.Show("No project is selected!");
                }
            }
            if (Text.Contains("{SolutionFile}"))
            {
                if (!string.IsNullOrEmpty(CurrentSolutionFile))
                    Text = Text.Replace("{SolutionFile}", CurrentSolutionFile);
                else
                    MessageBox.Show("No solution is open!");
            }
            if (Text.Contains("{ProjectName}"))
            {
                if (dockPanel1.ActiveDocument is CodeWindow)
                {
                    foreach (Project proj in _CurrentSolution.Projects)
                    {
                        bool shouldBreak = false;
                        foreach (string file in proj.Files)
                        {
                            if (CurrentSolutionDirectory + proj.RootDirectory + "\\" + file == (dockPanel1.ActiveDocument as CodeWindow).Code)
                            {
                                Text = Text.Replace("{ProjectName}", proj.Name);
                                shouldBreak = true;
                                break;
                            }
                        }
                        if (shouldBreak)
                            break;
                    }
                }
                else
                {
                    MessageBox.Show("No project is selected!");
                }
            }
            if (Text.Contains("{SolutionName}"))
            {
                if (!string.IsNullOrEmpty(CurrentSolutionFile))
                    Text = Text.Replace("{SolutionName}", _CurrentSolution.Name);
                else
                    MessageBox.Show("No solution is open!");
            }
            return Text;
        }

        private void keyboardShortcutsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            KeyboardShortcutsDialog dialog = new KeyboardShortcutsDialog();
            dialog.ShowDialog();
            SaveGlobalSettings();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            SaveCurrentDocument();
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void saveAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveAllDocuments();
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        void FileToolStripMenuItem3Click(object sender, EventArgs e)
        {
        	Project selectedProject = null;
        	
        	//Otherwise it throws a NullReferenceException
        	if (CurrentSolution != null)
        	{
        		foreach(Project proj in CurrentSolution.Projects)
        		{
        			foreach(string fName in proj.Files)
        			{
        				if (CurrentSolution.FocusedFile == fName)
        				{
        					selectedProject = proj;
        					break;
        				}
        			}
        		}
        	}
        	if (selectedProject != null)
        	{
        		//This causes errors if there is no project
        		//TODO: Fix the errors this method throws if there is no project
        		Explorer_NewFileRequested(sender, new NewFileEventArgs(selectedProject));
        	}
        	else
        	{
        		CodeWindow codeWindow = new CodeWindow(this);
        		codeWindow.Show(dockPanel1, DockState.Document);
        	}
        }
    }
}
